package com.hwy.widget.float_window

import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.hwy.widget.R
import kotlin.math.max

/**
 * =======================================
 * 作者: hewenyu
 * 日期: 2022/3/14 22:04
 * 说明: 悬浮窗通用属性布局
 * =======================================
 */
class FloatWindowLayout(context: Context, attrs: AttributeSet?) : ConstraintLayout(context, attrs) {

    companion object {

        /**
         * 悬浮窗默认的宽度与屏幕宽度百分比
         */
        private const val DEFAULT_WIDTH_PERCENT = 0.7F

        /**
         * 悬浮窗默认的高度与屏幕高度百分比
         */
        private const val DEFAULT_HEIGHT_PERCENT = 0.25F

    }

    /**
     * 调整坐标按钮
     */
    private var ivWindowHead: ImageView? = null

    /**
     * 尺寸缩放按钮
     */
    private var ivDragSize: ImageView? = null

    /**
     * 关闭按钮
     */
    private var ivWindowClose: ImageView? = null

    /**
     * 悬浮窗名称
     */
    private var tvTitle: AppCompatTextView? = null

    /**
     * 内容视图
     */
    private var flContent: FrameLayout? = null

    private var startX = 0
    private var startY = 0

    private var wmManager: WindowManager? = null
    private var wmParam: WindowManager.LayoutParams? = null

    /**
     * 悬浮窗是否显示
     * true:显示
     * false:隐藏
     */
    private var isShow = false

    var onDismissListener: OnDismissListener? = null

    private var minWindowWidth = 0
    private var minWindowHeight = 0

    override fun onFinishInflate() {
        super.onFinishInflate()
        ivWindowHead = findViewById(R.id.iv_window_head)
        ivWindowClose = findViewById(R.id.iv_window_close)
        tvTitle = findViewById(R.id.tv_title)
        ivDragSize = findViewById(R.id.iv_drag_size)
        flContent = findViewById(R.id.fl_content)

        // 获取 WindowManager 服务
        wmManager = context.getSystemService(Context.WINDOW_SERVICE) as? WindowManager
        wmParam = WindowManager.LayoutParams()
        initParam()
        initView()
        initListener()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        minWindowWidth = (ivWindowHead?.width ?: 0) + (ivWindowClose?.width ?: 0)
        minWindowHeight = (ivWindowHead?.height ?: 0) + (ivDragSize?.height ?: 0)
    }

    private fun initParam() {

        val screenWidth = context.resources.displayMetrics.widthPixels
        val screenHeight = context.resources.displayMetrics.heightPixels

        wmParam?.run {
            // 设置颜色格式支持透明度
            format = PixelFormat.RGBA_8888
            // 设置悬浮窗显示的位置，左上角对齐
            gravity = Gravity.LEFT or Gravity.TOP
            x = 0
            y = 0
            // 设置悬浮窗默认的宽高
            width = (screenWidth * DEFAULT_WIDTH_PERCENT).toInt()
            height = (screenHeight * DEFAULT_HEIGHT_PERCENT).toInt()
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            flags =
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    .or(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
                    // 延申到状态栏
//                    .or(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
                    .or(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR)
                    .or(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)
        }
    }

    private fun initListener() {
        ivWindowHead?.run {
            setOnTouchListener { _, event ->
                when (event.actionMasked) {
                    MotionEvent.ACTION_DOWN -> {
                        startX = event.rawX.toInt()
                        startY = event.rawY.toInt()
                    }
                    MotionEvent.ACTION_MOVE -> {
                        wmParam?.run {
                            x += event.rawX.toInt() - startX
                            y += event.rawY.toInt() - startY
                            wmManager?.updateViewLayout(this@FloatWindowLayout, this)
                        }
                        startX = event.rawX.toInt()
                        startY = event.rawY.toInt()
                    }
                }
                return@setOnTouchListener true
            }
        }

        ivDragSize?.run {
            setOnTouchListener { _, event ->
                when (event.actionMasked) {
                    MotionEvent.ACTION_DOWN -> {
                        startX = event.rawX.toInt()
                        startY = event.rawY.toInt()
                    }
                    MotionEvent.ACTION_MOVE -> {
                        wmParam?.run {
                            width = max((event.rawX.toInt() - startX + width), minWindowWidth)
                            height = max((event.rawY.toInt() - startY + height), minWindowHeight)
                            wmManager?.updateViewLayout(this@FloatWindowLayout, this)
                        }
                        startX = event.rawX.toInt()
                        startY = event.rawY.toInt()
                    }
                }
                return@setOnTouchListener true
            }
        }

        ivWindowClose?.run {
            setOnClickListener {
                wmManager?.removeView(this@FloatWindowLayout)
                onDismissListener?.onDismiss(this@FloatWindowLayout)
            }
        }

    }

    private fun initView() {
        tvTitle?.run {
            text = "title"
        }
    }

    fun show() {
        if (!isShow) {
            wmManager?.addView(this, wmParam)
            isShow = !isShow
        }
    }

    fun setContentView(view: View?) {
        view?.run {
            flContent?.run {
                this.removeAllViews()
                addView(view)
            }
        }
    }

    fun setTitle(text: CharSequence?) {
        tvTitle?.text = text
    }

    interface OnDismissListener {

        fun onDismiss(layout: FloatWindowLayout)

    }

}